﻿package com.cf.core.view.ScrollBar{
	import flash.display.*
	import flash.events.*;
	import flash.geom.Rectangle;
	import flash.geom.Rectangle;
	import com.greensock.*;
	import com.greensock.easing.*;
	import com.cf.core.Utils.tools;
	import com.cf.core.view.MySprite;
	
	public class track extends Sprite {
		private var MIN_GRABBER_HEIGHT:int=80;
		
		// value
		private var G_trackColor:uint;
		private var G_grabberColor:uint;
		private var G_grabberPressColor:uint;
		private var G_gripColor:uint;
		private var G_trackThickness:int;
		private var G_grabberThickness:int;
		private var G_pressed:Boolean;
		private var G_easeAmount:int;
		private var G_drawUI:Boolean;
		
		// object
		private var G_track:Sprite;
		private var G_grabber:Sprite;
		private var G_target:DisplayObjectContainer;
		public function get grabber():*{return G_grabber}
		public function get target(){return G_target}
		
		// default UI, static Child
		public function get grabberBG():Sprite{return G_grabber.getChildByName('bg') as Sprite}
		public function get grabberGRIP():Sprite{return G_grabber.getChildByName('grip') as Sprite}
		public function get arrowUP():Sprite{return G_grabber.getChildByName('arrowup') as Sprite}
		public function get arrowDN():Sprite{return G_grabber.getChildByName('arrowdn') as Sprite}
		
		// API
		private var G_length:Number=0;
		public function set length(_n:Number):void{G_length=_n; reload()}
		public function get length():Number{return G_length}
		private var G_target_width:Boolean=false;
		public function set checkWidth(_f:Boolean):void{G_target_width=_f;}
		public function set checkHeight(_f:Boolean):void{G_target_width=!_f}
		private var G_value:Number=0; // 0~100
		public function get value():Number{return G_value}
		public function set value(_n:Number):void{
			var _total = (G_track.height-G_grabber.height);
			if(_n<0)_n=0;else if(_n>100)_n=100;
			G_value=_n;
			G_grabber.y = Math.round(_n*_total/100);
			updateValue();
		}//fn
		
		public function track(c:DisplayObjectContainer, tc:*=0x666666, gc:*=0xCCCCCC, gpc:uint=0xFFFFFF, grip:uint=0x999999, tt:int=14, gt:int=14 ):void{
			//
			// Call style 1 - gen or access color
			// track(trackColor, grabberColor, gripColor, trackThickness, grabberThickness, G_trackThickness, G_grabberThickness);
			//
			// Call style 2 - direct access DisplayObject
			// track(TrackObj_y, GrabberObj_y);
			//
			G_drawUI=false;
			G_target=c;
			if(tc is String) G_track=tools.searchLib(tc);
			else if (tc is DisplayObject) G_track=tc;
			else tc=0x666666;
			if(gc is String) G_grabber=tools.searchLib(gc);
			else if (gc is DisplayObject) G_grabber=gc;
			else gc=0xCCCCCC;
			if( tc is uint && gc is uint){
				G_drawUI=true;
				G_trackColor = tc;
				G_grabberColor = gc;
				G_grabberPressColor = gpc;
				G_gripColor = grip;
				G_trackThickness = tt;
				G_grabberThickness = gt;
				G_track = createTrack();
				G_grabber = createGrabber();
			}else{
				// patch for onTrackClick
				G_trackThickness = G_track.height;
			}//if
			init();
		}//fn
		//
		//	Listener
		//
		public function stopMove():void{
			onUpListener();
		}//fn
		private function onTrackClick(e:MouseEvent):void{
			var p:int;
			var js:Number = ((this.length/G_track.height*0.1)<10)? 10:(this.length/G_track.height*0.1);// 150;
			p = Math.ceil( (e.localY/G_trackThickness)*G_track.height); // (e.stageY);
			if(p < G_grabber.y){
				// Go UP
				if(G_grabber.y-js < 0){
					TweenLite.to(G_grabber, 0.5, {y:0, onComplete:grabberFix, overwrite:1});
				}else{
					js=-1*js;
					TweenLite.to(G_grabber, 0.5, {y:js.toString(), onComplete:grabberFix});
				}//if
			}else{
				// GO DOWN
				if( (G_grabber.y+G_grabber.height+js) > G_track.height){
					TweenLite.to(G_grabber, 0.5, {y:(G_track.height - G_grabber.height), onComplete:grabberFix, overwrite:1});
				}else{
					TweenLite.to(G_grabber, 0.5, {y:js.toString(), onComplete:grabberFix});
				}//if
			}//if
			addEventListener(Event.ENTER_FRAME, updateValue);
		}//fn
		protected function grabberFix():void{
			if(G_grabber.y < 0) G_grabber.y = 0;
			if(G_grabber.y + G_grabber.height > G_track.height) G_grabber.y = G_track.height - G_grabber.height;
			removeEventListener(Event.ENTER_FRAME, updateValue);
		}//fn
		private function onDownListener(e:MouseEvent):void{
			G_pressed=true;
			G_grabber.startDrag(false, new Rectangle(0, 0, 0, G_track.height - grabberBG.height));
			addEventListener(Event.ENTER_FRAME, updateValue);
			dispatchEvent(new ScrollEvent(ScrollEvent.DOWN));
		}//fn
		private function onUpListener(e:MouseEvent = null):void{
			if (G_pressed){
				G_pressed = false;
				G_grabber.stopDrag();
				removeEventListener(Event.ENTER_FRAME, updateValue);
				// stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMoveListener);
			}
			dispatchEvent(new ScrollEvent(ScrollEvent.UP));
		}//fn
		private function onAddedToStage(e:Event):void{
			removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
			stage.addEventListener(MouseEvent.MOUSE_UP, onUpListener, false, 0, true);
			G_grabber.addEventListener(MouseEvent.MOUSE_DOWN, onDownListener, false, 0, true);
			G_track.addEventListener(MouseEvent.CLICK, onTrackClick, false, 0, true);
		}//fn
		public function RELEASE(e:*=null):void{
			stage.removeEventListener(MouseEvent.MOUSE_UP, onUpListener);
			G_grabber.removeEventListener(MouseEvent.MOUSE_DOWN, onDownListener);
			G_track.removeEventListener(MouseEvent.CLICK, onTrackClick);
			try{
				removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
			}catch(e){}
		}//fn
		private function init():void{
			G_grabber.buttonMode = true;
			this.addChildAt(G_track, 0);
			this.addChildAt(G_grabber, 1);
			addEventListener(Event.ADDED_TO_STAGE, onAddedToStage, false, 0, true);
			G_pressed=false;
			G_easeAmount=5;
		}//fn
		public function reload():void{
			// reset the object position
			var _tmpH:Number;
			var _tarlength:Number;
			G_track.height = this.length;
			if(G_target_width) _tarlength=G_target.width; else _tarlength=G_target.height;
			if( _tarlength<= G_track.height){
				this.visible=false;
			}else{
				this.visible=true;
				if(G_drawUI){
					_tmpH = (G_track.height / _tarlength)*100;
					grabberBG.height = (_tmpH<MIN_GRABBER_HEIGHT)?MIN_GRABBER_HEIGHT:_tmpH;
					grabberGRIP.y = grabberBG.height/2-3;
					arrowUP.y = 8;
					arrowDN.y = grabberBG.height - 8;
				}//if
			}//if
		}//fn
		private function updateValue(e:*=null):void{
			var _total:Number;
			var _curr = G_grabber.y;
			var _tarlength:Number;
			if(G_target_width) _tarlength = G_target.width; else _tarlength = G_target.height;
			G_grabber.height = _tarlength / this.length;				// how height of the grabber.
			if( _tarlength>=this.length ) this.visible=true; else this.visible=false;
			if( G_grabber.height<MIN_GRABBER_HEIGHT) G_grabber.height=MIN_GRABBER_HEIGHT;
			_total = (G_track.height-G_grabber.height);					// total value pixal of the track can move.
			G_value = Math.ceil(_curr/_total*100);	// don't use this.value to setup. will effect reload() in deadloop.
			dispatchEvent(new ScrollEvent(ScrollEvent.CHANGE, {value: this.value}));
		}//fn
		
		//
		// UI Generators
		//
		private function createTrack():Sprite{
			// [BG]
			var t:Sprite = new Sprite();
			t.graphics.beginFill(G_trackColor); 
			t.graphics.drawRect(0, 0, G_trackThickness, G_trackThickness);
			t.graphics.endFill();
			return t;
		}//fn
		private function createGrabber():Sprite{
			var t:Sprite = new Sprite();
			var _bg:MySprite = new MySprite();
			var _grip:Sprite = createGrabberGrip();
			var _a1:Sprite = createPixelArrow();
			var _a2:Sprite = createPixelArrow();
			_bg.name="bg";
			_grip.name="grip";
			_a1.name="arrowup";
			_a2.name="arrowdn";
			_bg.bgColor=G_grabberColor;
			_bg.Rect(0,0, G_trackThickness, MIN_GRABBER_HEIGHT);
			_a1.rotation = -90;
			_a1.x = ((G_grabberThickness - 7) / 2) + 1;
			_a2.rotation = 90;
			_a2.x = ((G_grabberThickness - 7) / 2) + 6;
			t.addChildAt(_bg, 0);
			t.addChildAt(_a1, 1);
			t.addChildAt(_a2, 1);
			t.addChildAt(_grip, 2);
			return t;
		}//fn
		private function createGrabberGrip():Sprite{
			// [|||||]
			var w:int = 7;
			var xp:int = (G_grabberThickness - w) / 2;
			var t:Sprite = new Sprite();
			t.graphics.beginFill(G_gripColor, 1);
			t.graphics.drawRect(xp, 0, w, 1);
			t.graphics.drawRect(xp, 0 + 2, w, 1);
			t.graphics.drawRect(xp, 0 + 4, w, 1);
			t.graphics.drawRect(xp, 0 + 6, w, 1);
			t.graphics.drawRect(xp, 0 + 8, w, 1);
			t.graphics.endFill();
			return t;
		}//fn
		private function createPixelArrow():Sprite{
			// [<]
			var t:Sprite = new Sprite();			
			t.graphics.beginFill(G_gripColor, 1);
			t.graphics.drawRect(0, 0, 1, 1);
			t.graphics.drawRect(1, 1, 1, 1);
			t.graphics.drawRect(2, 2, 1, 1);
			t.graphics.drawRect(1, 3, 1, 1);
			t.graphics.drawRect(0, 4, 1, 1);
			t.graphics.endFill();
			return t;
		}//fn
	}//class
}//package